package xj.app;

import static xj.app.BaseApplicationFrame.getResourceString;

import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import java.util.Map;

import javax.swing.*;
import org.jdesktop.swingx.*;

public abstract class BaseApplication 
  implements Application {

  public BaseApplicationFrame getApplicationFrame() { 
    return frame; 
  }

  public JFrame getJFrame() {
    return frame.getJFrame(); 
  }

  //
  // Basic application wide properties 
  // 

  public String getAppName() {
    return frame.getAppName();
  }

  public String getAppDir() {
    return frame.getAppDir();
  }

  public String getDefaultDir() {
    return frame.getDefaultDir();
  }

  public String getVersion() {
    return frame.getVersion();
  }

  public String getBuild() {
    return frame.getBuild();
  }

  public String getRevision() {
    return frame.getRevision();
  }

  public String getReleaseDate() {
    return frame.getReleaseDate();
  }

  public String getNamespaceURI() {
    return frame.getNamespaceURI();
  }

  public String getNamespacePrefix() {
    return frame.getNamespacePrefix();
  }

  public int getSwitchAppMenuIndex() {
    return -1; 
  }

  public boolean isShowing() { 
    return (this == frame.getCurrentApplication());
  }

  //
  // Project mode 
  //

  public boolean isProjectMode() {
    return projectMode;
  }

  public boolean isSingleDocumentMode() {
    return singleDocumentMode;
  }

  public void setProjectMode(boolean projectMode) {
    this.projectMode = projectMode;
  }
  
  public void setSingleDocumentMode(boolean singleDocumentMode) {
    this.singleDocumentMode = singleDocumentMode;
  }

  //
  // Tools for visual editing 
  // 

  public void setDrawToolkit(DrawToolkit toolkit) {
    this.toolkit = toolkit;
  }

  public DrawToolkit getDrawToolkit() {
    return toolkit;
  }

  public DrawTool getTool(String name) {
    if (toolkit != null) {
      return toolkit.getTool(name);
    }
    return null;
  }

  public void addTool(DrawTool tool) {
    if (toolkit != null && tool != null) {
      toolkit.addTool(tool);
    }
  }

  public void addTool(String name, DrawTool tool) {
    if (toolkit != null && tool != null) {
      toolkit.addTool(name, tool);
    }
  }

  public void setAutoSaveInterval(int v) { 
    if (v < 30) 
      v = 30; 
    autoSaveInterval = v;
  }

  public void startAutoSave(AutoSaveListener al) {
    if (auto == null) { 
      auto = new AutoSave(al, autoSaveInterval);
    }
  }

  public void stopAutoSave() {
    if (auto != null) {
      auto.interrupt();
      auto = null;
    }
  }

  public void setChanged(boolean changed) {}

  public void stopThreads() {}

  public boolean exitApp() {
    return true; 
  }

  public void hourGlassOn() {
    if (frame != null) { 
      frame.hourGlassOn();
    }
  }

  public void hourGlassOff() {
    if (frame != null) { 
      frame.hourGlassOff();
    }
  }
  
  protected void arrangePanels() {}

  protected void resetDockingPanel() { 
    if (dockingPanel != null) { 
      dockingPanel.removeAll(); 
      for (ClosablePanel cp : closablePanelMap.values()) { 
	if (cp.isClosed()) { 
	  addIconToDockingPanel(cp);
	}
      }
    }
  }  

  public ClosablePanel getClosablePanel(String name) {
    return closablePanelMap.get(name);
  }

  public JXTitledPanel getJXTitledPanel(String name) {
    ClosablePanel cpanel = closablePanelMap.get(name);
    if (cpanel != null) { 
      JComponent comp = cpanel.getComponent(); 
      if (comp instanceof JXTitledPanel) { 
	return (JXTitledPanel) comp;
      }
    }
    return null;
  }

  public void removeDockedIcon(String name) {
    if (name != null) { 
      int n = dockingPanel.getComponentCount();
      for (int i = 0; i < n; i++) { 
	Component comp = dockingPanel.getComponent(i);
	if (comp instanceof JButton) { 
	  JButton b = (JButton) comp; 
	  String cmd = b.getActionCommand();
	  if (name.equals(cmd)) { 
	    dockingPanel.remove(b);
	    break; 
	  }
	}
      }
    }
  }

  public void openClosablePanel(String name) {
    if (name != null) { 
      ClosablePanel cp = closablePanelMap.get(name);
      if (cp != null && 
          cp.isClosed()) { 
        cp.setClosed(false); 
        arrangePanels();
        BaseApplicationFrame frame = getApplicationFrame();
        frame.updateAppUI();
      }
    }
  }

  public void closeClosablePanel(String name) {
    if (name != null) { 
      ClosablePanel cp = closablePanelMap.get(name);
      if (cp != null && 
          cp.isClosable() &&
          !cp.isClosed()) { 
	JComponent comp = cp.getComponent();
        BaseApplicationFrame frame = getApplicationFrame();
	WindowClosingAnimation ani = new WindowClosingAnimation(frame.getJFrame());
	ani.setStartComponent(comp);
        cp.setClosed(true); 
        arrangePanels();
        frame.updateAppUI();
	JComponent b = addIconToDockingPanel(cp);
	ani.setEndComponent(b);
	ani.start();
      }
    }
  }

  protected void addIconToDockingPanel(String name) {
    if (name != null) { 
      ClosablePanel cp = closablePanelMap.get(name);
      addIconToDockingPanel(cp);
    }
  }

  protected JComponent addIconToDockingPanel(ClosablePanel cp) { 
    if (cp != null && 
	cp.isClosable()) { 
      cp.setClosed(true); 
      Icon icon = cp.getIcon(); 
      if (icon != null) { 
	String name = cp.getName();
	JButton b = new JButton(icon);
	b.setActionCommand(name); 
	String tip = getResourceString(name + ".Panel.title");
	if (tip == null) { 
	  tip = name; 
	}
	b.setToolTipText(tip); 
	b.addActionListener(new ActionListener() {
	    public void actionPerformed(ActionEvent evt) { 
	      if (evt != null) { 
		JButton b = (JButton) evt.getSource();
		String cmd = b.getActionCommand();
		openClosablePanel(cmd);
		dockingPanel.remove(b);
	      }
	    }
	  });
	dockingPanel.add(b);
	dockingPanel.revalidate();
	return b;
      }
    }
    return null;
  }

  protected void detachClosablePanel(String name) { 
    if (name != null) { 
      ClosablePanel cp = closablePanelMap.get(name);
      if (cp != null) { 
	if (cp.isClosable() &&
	    !cp.isClosed()) { 
	  cp.setClosed(true); 
	  arrangePanels();
	  BaseApplicationFrame frame = getApplicationFrame();
	  frame.updateAppUI();
	}

	ClosableFrame cf = new ClosableFrame(cp);
	cf.addWindowListener(new WindowAdapter() { 
	    @Override
	    public void windowClosing(WindowEvent event) {
	      ClosableFrame cf = (ClosableFrame) event.getSource(); 
	      BaseApplicationFrame frame = getApplicationFrame();
	      WindowClosingAnimation ani = new WindowClosingAnimation(frame.getJFrame());
	      ani.setStartComponent(cf);
	      String name = cf.getName(); 
	      cf.setVisible(false);
	      Container cont = cf.getContentPane();
	      if (name != null) { 
		ClosablePanel cp = closablePanelMap.get(name);
		cp.setContentContainer(cont);
		JComponent b = addIconToDockingPanel(cp);
		ani.setEndComponent(b);
		ani.start();
	      }
	    }
	  });
	cf.setVisible(true);
      }
    }
  }

  protected BaseApplication(BaseApplicationFrame frame) {
    this.frame = frame; 
    dockingPanel = new DockingPanel(); 
  }

  protected BaseApplicationFrame frame; 

  protected boolean projectMode = false;

  protected boolean singleDocumentMode = true;

  protected DrawToolkit toolkit = null;

  protected AutoSave auto = null;

  protected int autoSaveInterval = 30; 

  protected DockingPanel dockingPanel = null;

  protected Map<String, ClosablePanel> closablePanelMap = new HashMap<String, ClosablePanel>(); 

}